Thread: [HELP] C - pointers, structures and lists.

  1. #16
    Registered User
    Join Date
    Jun 2013
    Location
    Portugal
    Posts
    11
    Yes rcgldr, C supports the way I declared those structures and typedefs, at least Xcode didn't complain about it and I've seen my teachers using this every now and then.

    I'll use the fgets() function as you said, but could you explain me why exactly is it better the way you did?

    Lastly, I've tried to save the closet nodes in last like I did with the first function but I failed and I got even more confused, would you show me a fast example on how would you do it ?

    Thank you!

  2. #17
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by sigkill View Post
    I'll use the fgets() function as you said, but could you explain me why exactly is it better the way you did?
    fread reads in binary data. You want to convert the text lines into numeric values, so would be best to use fgets() to read lines of text, and sscanf() to convert the strings in the lines of text into numbers.

    Quote Originally Posted by sigkill View Post
    Lastly, I've tried to save the closet nodes in last like I did with the first function.
    Just copy the first function and change the names from corredores to armarios.

    You're going to need a variable to store a pointer to the first corridor.

    Again, if you put the next pointers first in the structures, you can use common code with casting to work with a list of structures, for example:

    Code:
    typedef struct node{
        struct node *prox;
    }*ptr_node;
    
    typedef struct armarios {
        struct armarios * prox;
        int id;
        int nr_prods;
    }*ptr_armr;
    
    typedef struct corredores {
        struct corredores * prox;
        int id;
        ptr_armr pont_armario;
    }*ptr_corr;
    
    ptr_node findlastnode (ptr_node); /* finds the last node */
    
    /* ... */
    
    ptr_corr pfirst_corr;
    ptr_corr plast_corr;
    ptr_armr pfirst_armr;
    ptr_armr plast_armr;
    
    /* ... */
    
        plast_corr = (ptr_corr) findlastnode((ptr_node) pfirst_corr);
    
    /* ... */
    
        plast_armr = (ptr_armr) findlastnode((ptr_node) pfirst_armr);
    Last edited by rcgldr; 06-07-2013 at 05:08 PM.

  3. #18
    Registered User
    Join Date
    Jun 2013
    Location
    Portugal
    Posts
    11
    Code:
    ptr_corr carrega_lista(ptr_corr p)
    {
        int i, nr_cors=0, nr_arms=0;
        ptr_corr novo, aux;
        ptr_armr a = NULL;
        
        FILE *f = fopen(FILENAME, RDMODE);
        
        fread(&nr_cors,sizeof(int),1,f);
        fread(&nr_arms,sizeof(int),1,f);
        fclose(f);
        
        for(i=0; i < nr_cors; i++){
            novo = malloc(sizeof(corrs));
            if(novo == NULL)
            {
                printf("Erro ao alocar memoria!\n");
                return p;
            }
            novo->id = i+1;
            novo->pont_armario = NULL;
            novo->prox = NULL;
            
            if(p == NULL)
                p = novo;
            else
            {
                aux = p;
                while(aux->prox != NULL)
                    aux = aux->prox;
                aux->prox = novo;
            }
        }
        a = carrega_armario(p, a, nr_arms);
    
    
        return p;
    }
    ptr_armr carrega_armario(ptr_corr p, ptr_armr a, int nr_armarios)
    {
        FILE *f = fopen(FILENAME, RDMODE);
        
        ptr_armr novo, aux;
        int i=0;
    
    
        
        while(p != NULL)
        {
            for(i=0; i > nr_armarios; i++){
            
                novo = malloc(sizeof(armrs));
        
                novo->id = i+1;
                novo->nr_prods = 0;
                novo->prox = NULL;
                
                if(a == NULL)
                {
                    a = novo;
                    p->pont_armario = novo;
                }
                else
                {
                    aux = a;
                    while(aux->prox != NULL)
                        aux = aux->prox;
                    aux->prox = novo;
                }
            }
            p = p->prox;
        }
        fclose(f);
        return a;
    }
    Only prints the corridors now.. :/

    EDIT: Also rcgldr, I've noticed that your technique with the next pointers it's useful indeed, I've just not used yet because I'm panicking to get this right first..

  4. #19
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Lets fix the problems one at a time. First add a printf() to see what the program does with nr_cors, and nr_arms :

    Code:
    FILE * f;
    int nr_cors;
    int nr_arms;
    
    /* ... */
    
        f = fopen(FILENAME, RDMODE);
        fread(&nr_cors,sizeof(int),1,f);
        fread(&nr_arms,sizeof(int),1,f);
        fclose(f);
    
        printf("nr_cors = %d, nr_arms = %d\n", nr_cors, nr_arms);
    Next change this to use fgets() and sscanf():
    Code:
    char fline[80];
    FILE * f;
    int nr_cors;
    int nr_arms;
    
    /* ... */
    
        f = fopen(FILENAME, RDMODE);
        fgets(fline, sizeof(fline), f);
        sscanf(fline, "%d %d", &nr_cors, &nr_arms);
        fclose(f);
    
        printf("nr_cors = %d, nr_arms = %d\n", nr_cors, nr_arms);

  5. #20
    Registered User
    Join Date
    Jun 2013
    Location
    Portugal
    Posts
    11
    The first one, with the freads, returned correctly, 5 corridors and 3 closets. The one with the fgets and sscanf, nr_cors and nr_arms returned both 0.

  6. #21
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by sigkill View Post
    The first one, with the freads, returned correctly, 5 corridors and 3 closets. The one with the fgets and sscanf, nr_cors and nr_arms returned both 0.
    Then your compiler is different than all the compilers I'm tried with this program. For the first one with freads(), I get nr_cors = 171122741, nr_arms = 64804, and for the second one with fgets() and sscanf() I get nr_cors = 5, nr_arms = 3.

    That 171122741 is the result of reading the first line which is "5 3\n" as if it were a 4 byte integer, or in hex 35 20 33 0A in little endian mode, which results in hex 0A332035 which equals 171122741.

    update - I'll be away for a few hours, but I will return with more fixes.
    Last edited by rcgldr; 06-07-2013 at 06:54 PM.

  7. #22
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    I'm using a text file for input, perhaps your file is binary. Here is example code that creates a list of corridors, each with a list of closets. I did not include any code that frees up the memory in this partial example:

    Code:
    #define FILENAME "example.txt"
    #define RDMODE "r"
    
    #include <stdio.h>
    #include <malloc.h>
    
    typedef struct node{
        struct node *prox;
    }*ptr_node;
    
    typedef struct armarios {
        struct armarios * prox;
        int id;
        int nr_prods;
    }*ptr_armr;
    
    typedef struct corredores {
        struct corredores * prox;
        int id;
        ptr_armr ptr_armario;
    }*ptr_corr;
    
    ptr_corr carrega_corr(int, int);
    void carrega_armr(ptr_corr, int);
    
    int main (void)
    {
    FILE * f;
    char fline[80];
    int nr_cors;
    int nr_arms;
    ptr_corr pc;
    
        f = fopen(FILENAME, RDMODE);
        fgets(fline, sizeof(fline), f);
        sscanf(fline, "%d %d", &nr_cors, &nr_arms);
        fclose(f);
    
        printf("nr_cors = %d, nr_arms = %d\n", nr_cors, nr_arms);
    
        pc = carrega_corr(nr_cors, nr_arms);
    
        return 0;
    }
    
    ptr_corr carrega_corr(int nr_cors, int nr_arms)
    {
        int i;
        ptr_corr pc = NULL;     /* current ptr */
        ptr_corr px;            /* previous ptr */
        ptr_corr pf;            /* first ptr */
       
        for(i=0; i < nr_cors; i++){
            px = pc;            /* save current ptr */
            pc = (ptr_corr) malloc(sizeof(struct corredores));
            if(pc == NULL)
            {
                printf("Erro ao alocar memoria!\n");
                return NULL;
            }
            pc->id = i+1;        /* initialize corr */
            pc->ptr_armario = NULL;
            pc->prox = NULL;
    
            carrega_armr(pc, nr_arms);
    
            if(i == 0)
                pf = pc;          /* save ptr to first corridor */
            else
                px->prox = pc;    /* set next ptr */
        }
    
        return pf;
    }
    
    void carrega_armr(ptr_corr pc, int nr_arms)
    {
        int i;
        ptr_armr pa = NULL;     /* current ptr */
        ptr_armr px;            /* previous ptr */
       
        for(i=0; i < nr_arms; i++){
            px = pa;            /* save current ptr */
            pa = (ptr_armr) malloc(sizeof(struct armarios));
            if(pa == NULL)
            {
                printf("Erro ao alocar memoria!\n");
                return;
            }
            pa->id = i+1;
            pa->nr_prods = 0;
            pa->prox = NULL;
    
            if(i == 0)
                pc->ptr_armario = pa; /* set ptr to first armario */
            else
                px->prox = pa;    /* set next ptr */
        }
    }
    Last edited by rcgldr; 06-07-2013 at 09:46 PM.

  8. #23
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Alternate example with main allocating closets for each corridor. This example is more generic:

    Code:
    #define FILENAME "x.in"
    #define RDMODE "r"
    
    #include <stdio.h>
    #include <malloc.h>
    
    typedef struct node{
        struct node *prox;
    }*ptr_node;
    
    typedef struct armarios {
        struct armarios * prox;
        int id;
        int nr_prods;
    }*ptr_armr;
    
    typedef struct corredores {
        struct corredores * prox;
        int id;
        ptr_armr ptr_armario;
    }*ptr_corr;
    
    ptr_corr carrega_corr(int);
    ptr_armr carrega_armr(int);
    
    int main (void)
    {
    FILE * f;
    char fline[80];
    ptr_corr pf;                /* ptr to fisrt */
    ptr_corr pc;                /* temp ptr */
    int nr_cors;
    int nr_arms;
    
        f = fopen(FILENAME, RDMODE);
        fgets(fline, sizeof(fline), f);
        sscanf(fline, "%d %d", &nr_cors, &nr_arms);
        fclose(f);
    
        printf("nr_cors = %d, nr_arms = %d\n", nr_cors, nr_arms);
    
        pf = carrega_corr(nr_cors);
        if(pf == NULL)
            goto exit0;
    
        for(pc = pf; pc != NULL; pc = pc->prox){
            pc->ptr_armario = carrega_armr(nr_arms);
            if(pc->ptr_armario == NULL)
                goto exit0;
        }
    
    exit0:
        return 0;
    }
    
    ptr_corr carrega_corr(int nr_cors)
    {
        int i;
        ptr_corr pc = NULL;     /* current ptr */
        ptr_corr px;            /* previous ptr */
        ptr_corr pf;            /* first ptr */
       
        for(i=0; i < nr_cors; i++){
            px = pc;            /* save current ptr */
            pc = (ptr_corr) malloc(sizeof(struct corredores));
            if(pc == NULL)
            {
                printf("Erro ao alocar memoria!\n");
                return NULL;
            }
            pc->id = i+1;       /* initialize corr */
            pc->ptr_armario = NULL;
            pc->prox = NULL;
            if(i == 0)
                pf = pc;        /* save ptr to first corridor */
            else
                px->prox = pc;  /* set next ptr */
        }
        return pf;
    }
    
    ptr_armr carrega_armr(int nr_arms)
    {
        int i;
        ptr_armr pa = NULL;     /* current ptr */
        ptr_armr px;            /* previous ptr */
        ptr_armr pf;            /* first ptr */
       
        for(i=0; i < nr_arms; i++){
            px = pa;            /* save current ptr */
            pa = (ptr_armr) malloc(sizeof(struct armarios));
            if(pa == NULL)
            {
                printf("Erro ao alocar memoria!\n");
                return NULL;
            }
            pa->id = i+1;       /* initialize armr */
            pa->nr_prods = 0;
            pa->prox = NULL;
            if(i == 0)
                pf = pa;        /* set ptr to first armario */
            else
                px->prox = pa;  /* set next ptr */
        }
        return pf;
    }
    Last edited by rcgldr; 06-08-2013 at 07:39 AM.

  9. #24
    Registered User
    Join Date
    Jun 2013
    Location
    Portugal
    Posts
    11
    Amazing! thank you so much. I've finally understood what you meant by putting the next pointers first in the structures as well!
    I've put that to work with binary file (yes, thats the type of file I'm working with) my next step will be to do the same but now for products, I'd suppose it's exactly the same thing you did with corridors and closets right?

    My doubt here is, if I'm going to make a different function to create the nodes for the products (like I did with closets) I know have to open the file again to read it, but know I need to start reading from the second line (the one with information for products in each closet) until the end, is this possible?

  10. #25
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by sigkill View Post
    I've put that to work with binary file (yes, thats the type of file I'm working with).
    You might want to consider using a text file, especially for the lines that have the products, since there are a variable number of products per closet.

    Quote Originally Posted by sigkill View Post
    I'd suppose it's exactly the same thing you did with corridors and closets right?
    Yes, but you'll need to get the data, (number of products then product id, product quantity, product id, product quantity, ... ,) in order to create a product list for a closet. You could read the values first into a large array, or you could read the file while creating a product list.

    Quote Originally Posted by sigkill View Post
    My doubt here is, if I'm going to make a different function to create the nodes for the products (like I did with closets) I know have to open the file again to read it, but know I need to start reading from the second line (the one with information for products in each closet) until the end, is this possible?
    Yes, just read the first line and ignore it. It's not clear to me how you are creating a binary file for the data. The example file you show in the first post appears to be a text file.

    If it is a text file, it may be easier to use fscanf() than fgets(), sscanf(), and strtok() (using strtok() to advance a pointer to the next pair of product id and product quantity numbers on a line).

    Note this entire program could be modified to use arrays of structures instead of linked lists, without a huge change to the program. If you run into trouble with the linked list method, I can explain how to switch it to using arrays.
    Last edited by rcgldr; 06-08-2013 at 12:45 PM.

  11. #26
    Registered User
    Join Date
    Jun 2013
    Location
    Portugal
    Posts
    11
    I've tried to do the same with products but instead of creating a new function to do that, I just tried to do everything on "carrega_armr", thing is it's not printing my list correctly. It's either bad programming on this function or my printing function.

    Does this make any sense to you as it does for me?

    Code:
    void carrega_armr(ptr_corr pc, int nr_arms)
    {
        FILE * f;
        int i, j, x=0, number=0;
        ptr_armr pa = NULL;     /* current ptr */
        ptr_armr px;            /* previous ptr */
        ptr_prod pd = NULL;     /* current ptr (prod)*/
        ptr_prod pxd;            /* previous ptr (prod) */
        
        f = fopen(FILENAME, RDMODE);
        fread(&number,sizeof(int),1,f);
        fread(&number,sizeof(int),1,f);
        
        printf("%d", number);
        
        for(i=0; i < nr_arms; i++){
            px = pa;            /* save current ptr */
            pa = (ptr_armr) malloc(sizeof(struct armarios));
            if(pa == NULL)
            {
                printf("Erro ao alocar memoria!\n");
                return;
            }
            pa->id = i+1;
            fread(&number,sizeof(int),1,f);
            pa->nr_prods = number;
            pa->ptr_produto = NULL;
            pa->prox = NULL;
            
            for(j = 0; j < number; j++){
                pxd = pd;
                pd = (ptr_prod) malloc(sizeof(struct produtos));
                if(pd == NULL)
                {
                    printf("Erro ao alocar memoria!\n");
                    return;
                }
                
                while(fread(&number,sizeof(int),1,f) == 1){
                    if((x%2) == 0 || (x == 0)) {
                        pd->id = number;
                    }
                    else
                    {
                        pd->qtd = number;
                    }
                    x++;
                }
                
                if(j == 0)
                    pa->ptr_produto = pd;
                else
                    pxd->prox = pd;
                
            }
            if(i == 0)
                pc->ptr_armario = pa; /* set ptr to first armario */
            else
                px->prox = pa;    /* set next ptr */
        }
        
        fclose(f);
    }
    Thank you.

  12. #27
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Try printing the "number" values you get to make sure they are correct.

  13. #28
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by sigkill View Post
    thing is it's not printing my list correctly.
    That's a pretty useless error description. How is it not printing correctly?

    Code:
                while(fread(&number,sizeof(int),1,f) == 1){
                    if((x%2) == 0 || (x == 0)) {
                        pd->id = number;
                    }
                    else
                    {
                        pd->qtd = number;
                    }
                    x++;
                }
    AFAIUI your file is just integers. Thus, this loop will read every integer until EOF and will always store it in the same structure (alternatively in "id" and in "qtd"), thus overwriting the values read before.

    Bye, Andreas

  14. #29
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    You need a second variable to read the numbers into. the for(j = 0; j < number; j++) ... loop will get messed up because you use fread() to change number inside the loop. For the inner loop fread, use a variable like numberpd (for number product).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Link Lists of Structures within Structures...
    By Zocheyado in forum C Programming
    Replies: 3
    Last Post: 04-17-2012, 04:21 PM
  2. Understanding linked lists, structures, and pointers
    By yougene in forum C Programming
    Replies: 5
    Last Post: 07-13-2011, 08:13 PM
  3. Can i do this: Structures and linked lists help
    By satory in forum C Programming
    Replies: 4
    Last Post: 04-25-2005, 07:49 AM
  4. structures/linked lists
    By xddxogm3 in forum C++ Programming
    Replies: 4
    Last Post: 09-27-2003, 11:06 PM
  5. Replies: 5
    Last Post: 04-11-2002, 11:29 AM